home *** CD-ROM | disk | FTP | other *** search
/ Delphi Developer's Kit 1996 / Delphi Developer's Kit 1996.iso / power / wfc007.000 / sample / watchdog / watchdog.cpp < prev    next >
Encoding:
C/C++ Source or Header  |  1995-12-22  |  10.4 KB  |  355 lines

  1. #include <wfc.h>
  2. #include "messages.h"
  3. #pragma hdrstop
  4.  
  5. /*
  6. ** Author: Samuel R. Blackburn
  7. ** CI$: 76300,326
  8. ** Internet: sammy@sed.csc.com
  9. **
  10. ** This is freeware as always...
  11. **
  12. ** You can use it any way you like.
  13. **
  14. ** Sample program that watches other services and restarts them if they fail.
  15. **
  16. ** Registration Database Entries:
  17. **
  18. ** MachineName, REG_SZ, name of machine to monitor, default is local machine
  19. ** NumberOfSecondsBetweenChecks, REG_DWORD, how long to sleep between heartbeats
  20. ** Services, REG_MULTI_SZ, names of services to watch for
  21. **
  22. ** Demonstrates the following classes in action:
  23. **   CRegistry
  24. **   CService 
  25. **   CServiceControlManager
  26. **   CServiceNameAndStatus
  27. */
  28.  
  29. #if defined( _DEBUG )
  30. #undef THIS_FILE
  31. static char BASED_CODE THIS_FILE[] = __FILE__;
  32. #endif
  33.  
  34. DWORD WINAPI worker_thread( LPVOID unused_parameter );
  35. VOID set_default_parameters( void );
  36.  
  37. int __cdecl main( int argc, LPTSTR *argv )
  38. {
  39.    if ( argc == 1 )
  40.    {
  41.       CService service( worker_thread );
  42.       service.Initialize( "WatchDog" );
  43.  
  44.       return( EXIT_SUCCESS );
  45.    }
  46.  
  47.    if ( argc == 2 )
  48.    {
  49.       if ( strcmpi( argv[ 1 ], "install" ) == 0 )
  50.       {
  51.          CServiceControlManager service_control_manager;
  52.  
  53.          service_control_manager.Open();
  54.  
  55.          if ( service_control_manager.Install( "WatchDog", "WatchDog", "%SystemRoot%\\System32\\WatchDog.exe" ) != TRUE )
  56.          {
  57.             printf( "Install failed, please see Application Log for details\n" );
  58.          }
  59.  
  60.          set_default_parameters();
  61.  
  62.          return( EXIT_SUCCESS );
  63.       }
  64.       else if ( strcmpi( argv[ 1 ], "remove" ) == 0 )
  65.       {
  66.          CServiceControlManager service_control_manager;
  67.  
  68.          service_control_manager.Open();
  69.  
  70.          if ( service_control_manager.Remove( "WatchDog" ) != TRUE )
  71.          {
  72.             printf( "Removing failed, please see Application Log for details\n" );
  73.          }
  74.  
  75.          return( EXIT_SUCCESS );
  76.       }
  77.       else if ( strcmpi( argv[ 1 ], "run" ) == 0 )
  78.       {
  79.          worker_thread( (LPVOID) 1 );
  80.          return( EXIT_SUCCESS );
  81.       }
  82.       else
  83.       {
  84.          printf( "Samuel R. Blackburn, WFC Sample Application\nUsage: %s [install|remove]\n", argv[ 0 ] );
  85.       }
  86.    }
  87.    else
  88.    {
  89.       printf( "Samuel R. Blackburn, WFC Sample Application\nUsage: %s [install|remove]\n", argv[ 0 ] );
  90.    }
  91.  
  92.    return( EXIT_SUCCESS );
  93. }
  94.  
  95.  
  96. DWORD WINAPI worker_thread( LPVOID )
  97. {
  98.    {
  99.       CEventLog log( "WatchDog" );
  100.  
  101.       log.Report( CEventLog::eventInformation, 0, MSG_WATCHDOG_SERVICE_STARTED );
  102.    }
  103.  
  104.    CStringArray names_of_services_to_keep_alive;
  105.  
  106.    DWORD number_of_seconds_to_sleep = 0;
  107.  
  108.    CString machine_name( "" );
  109.  
  110.    BOOL return_value = TRUE;
  111.  
  112.    {
  113.       CRegistry registry;
  114.  
  115.       if ( registry.Connect( CRegistry::keyLocalMachine ) != TRUE )
  116.       {
  117.          return( 0 );
  118.       }
  119.  
  120.       CString key_name( "SYSTEM\\CurrentControlSet\\Services\\WatchDog\\Parameters" );
  121.  
  122.       if ( registry.Open( key_name ) != TRUE )
  123.       {
  124.          return( 0 );
  125.       }
  126.  
  127.       registry.GetValue( "Services", names_of_services_to_keep_alive );
  128.       registry.GetValue( "NumberOfSecondsBetweenChecks", number_of_seconds_to_sleep );
  129.       registry.GetValue( "MachineName", machine_name );
  130.    }
  131.  
  132.    DWORD sleep_time = 1000 * number_of_seconds_to_sleep;
  133.  
  134.    if ( sleep_time < 2000 )
  135.    {
  136.       /*
  137.       ** Minimum sleep time is 2 seconds, this give the OS time to do other things
  138.       */
  139.  
  140.       sleep_time = 2000;
  141.    }
  142.  
  143.    int number_of_services_to_keep_alive = names_of_services_to_keep_alive.GetSize();
  144.  
  145.    CServiceControlManager service_control_manager;
  146.  
  147.    /*
  148.    ** Sleep for one minute, this is in case we are starting during boot-up. We want
  149.    ** to give the service control manager time to start all necessary services before
  150.    ** we begin restarting stopped services.
  151.    */
  152.  
  153.    Sleep( 60 );
  154.  
  155.    do
  156.    {
  157.       if ( machine_name.IsEmpty() )
  158.       {
  159.          return_value = service_control_manager.Open( GENERIC_READ, NULL, (char *) NULL );
  160.       }
  161.       else
  162.       {
  163.          return_value = service_control_manager.Open( GENERIC_READ, NULL, machine_name );
  164.       }
  165.  
  166.       if ( return_value == TRUE )
  167.       {
  168.          if ( service_control_manager.EnumerateStatus( SERVICE_INACTIVE ) == TRUE )
  169.          {
  170.             CStringArray stopped_services;
  171.  
  172.             CServiceNameAndStatus status;
  173.  
  174.             while( service_control_manager.GetNext( status ) == TRUE )
  175.             {
  176.                stopped_services.Add( status.lpServiceName );
  177.             }
  178.  
  179.             /*
  180.             ** Now that we have the service names, we need to see which services need to be started
  181.             */
  182.  
  183.             int number_of_stopped_services = stopped_services.GetSize();
  184.             int alive_index   = 0;
  185.             int stopped_index = 0;
  186.  
  187.             while( alive_index < number_of_services_to_keep_alive )
  188.             {
  189.                stopped_index = 0;
  190.  
  191.                while( stopped_index < number_of_stopped_services )
  192.                {
  193.                   if ( names_of_services_to_keep_alive[ alive_index ].CompareNoCase( stopped_services[ stopped_index ] ) == 0 )
  194.                   {
  195.                      /*
  196.                      ** We found one that died, let's start it
  197.                      */
  198.  
  199.                      service_control_manager.Start( names_of_services_to_keep_alive[ alive_index ] );
  200.  
  201.                      /*
  202.                      ** We restarted a service, time to record the event
  203.                      */
  204.  
  205.                      const char *string_array[ 1 ];
  206.  
  207.                      string_array[ 0 ] = (const char *) names_of_services_to_keep_alive[ alive_index ];
  208.  
  209.                      CEventLog event_log( "WatchDog" );
  210.                      event_log.Report( CEventLog::eventInformation, 0, MSG_WATCHDOG_RESTARTING_SERVICE, 1, (const char **) string_array );
  211.  
  212.                      /*
  213.                      ** pop out of the loop
  214.                      */
  215.  
  216.                      stopped_index = number_of_stopped_services;
  217.                   }
  218.  
  219.                   stopped_index++;
  220.                }
  221.  
  222.                alive_index++;
  223.             }
  224.          }
  225.       }
  226.  
  227.       service_control_manager.Close();
  228.       Sleep( sleep_time );
  229.    }
  230.    while( 1 );
  231.  
  232.    return( 0 );
  233. }
  234.  
  235. void set_default_parameters( void )
  236. {
  237.    CRegistry registry;
  238.  
  239.    if ( registry.Connect( CRegistry::keyLocalMachine ) == TRUE )
  240.    {
  241.       if ( registry.Create( "SYSTEM\\CurrentControlSet\\Services\\WatchDog\\Parameters" ) == TRUE )
  242.       {
  243.          DWORD default_sleep_time = 60;
  244.  
  245.          if ( registry.SetValue( "NumberOfSecondsBetweenChecks", default_sleep_time ) != TRUE )
  246.          {
  247.             LPVOID message_buffer = (LPVOID) NULL;
  248.  
  249.             ::FormatMessage( FORMAT_MESSAGE_ALLOCATE_BUFFER | FORMAT_MESSAGE_FROM_SYSTEM,
  250.                              NULL,
  251.                              registry.GetErrorCode(),
  252.                              MAKELANGID( LANG_ENGLISH, SUBLANG_ENGLISH_US ),
  253.                    (LPTSTR) &message_buffer,
  254.                              0,
  255.                              NULL );
  256.  
  257.             const char *string_array[ 2 ];
  258.  
  259.             string_array[ 0 ] = "SYSTEM\\CurrentControlSet\\Services\\WatchDog\\Parameters\\NumberOfSecondsBetweenChecks";
  260.             string_array[ 1 ] = (const char *) message_buffer;
  261.  
  262.             CEventLog event_log( "WatchDog" );
  263.             event_log.Report( CEventLog::eventError, 0, MSG_CANT_SET_REGISTRY_ENTRY, 2, (const char **) string_array );
  264.  
  265.             if ( message_buffer != NULL )
  266.             {
  267.                ::LocalFree( message_buffer );
  268.             }
  269.          }
  270.  
  271.          CStringArray strings;
  272.  
  273.          strings.RemoveAll();
  274.  
  275.          strings.Add( "" );
  276.  
  277.          if ( registry.SetValue( "Services", strings ) != TRUE )
  278.          {
  279.             LPVOID message_buffer = (LPVOID) NULL;
  280.  
  281.             ::FormatMessage( FORMAT_MESSAGE_ALLOCATE_BUFFER | FORMAT_MESSAGE_FROM_SYSTEM,
  282.                              NULL,
  283.                              registry.GetErrorCode(),
  284.                              MAKELANGID( LANG_ENGLISH, SUBLANG_ENGLISH_US ),
  285.                    (LPTSTR) &message_buffer,
  286.                              0,
  287.                              NULL );
  288.  
  289.             const char *string_array[ 2 ];
  290.  
  291.             string_array[ 0 ] = "SYSTEM\\CurrentControlSet\\Services\\WatchDog\\Parameters\\Services";
  292.             string_array[ 1 ] = (const char *) message_buffer;
  293.  
  294.             CEventLog event_log( "WatchDog" );
  295.             event_log.Report( CEventLog::eventError, 0, MSG_CANT_SET_REGISTRY_ENTRY, 2, (const char **) string_array );
  296.  
  297.             if ( message_buffer != NULL )
  298.             {
  299.                ::LocalFree( message_buffer );
  300.             }
  301.          }
  302.       }
  303.       else
  304.       {
  305.          LPVOID message_buffer = (LPVOID) NULL;
  306.  
  307.          ::FormatMessage( FORMAT_MESSAGE_ALLOCATE_BUFFER | FORMAT_MESSAGE_FROM_SYSTEM,
  308.                           NULL,
  309.                           registry.GetErrorCode(),
  310.                           MAKELANGID( LANG_ENGLISH, SUBLANG_ENGLISH_US ),
  311.                 (LPTSTR) &message_buffer,
  312.                           0,
  313.                           NULL );
  314.  
  315.          const char *string_array[ 2 ];
  316.  
  317.          string_array[ 0 ] = "SYSTEM\\CurrentControlSet\\Services\\WatchDog\\Parameters";
  318.          string_array[ 1 ] = (const char *) message_buffer;
  319.  
  320.          CEventLog event_log( "WatchDog" );
  321.          event_log.Report( CEventLog::eventError, 0, MSG_CANT_CREATE_REGISTRY_KEY, 2, (const char **) string_array );
  322.  
  323.          if ( message_buffer != NULL )
  324.          {
  325.             ::LocalFree( message_buffer );
  326.          }
  327.       }
  328.    }
  329.    else
  330.    {
  331.       LPVOID message_buffer = (LPVOID) NULL;
  332.  
  333.       ::FormatMessage( FORMAT_MESSAGE_ALLOCATE_BUFFER | FORMAT_MESSAGE_FROM_SYSTEM,
  334.                        NULL,
  335.                        registry.GetErrorCode(),
  336.                        MAKELANGID( LANG_ENGLISH, SUBLANG_ENGLISH_US ),
  337.              (LPTSTR) &message_buffer,
  338.                        0,
  339.                        NULL );
  340.  
  341.       const char *string_array[ 2 ];
  342.  
  343.       string_array[ 0 ] = "keyLocalMachine";
  344.       string_array[ 1 ] = (const char *) message_buffer;
  345.  
  346.       CEventLog event_log( "WatchDog" );
  347.       event_log.Report( CEventLog::eventError, 0, MSG_CANT_CONNECT_TO_REGISTRY, 2, (const char **) string_array );
  348.  
  349.       if ( message_buffer != NULL )
  350.       {
  351.          ::LocalFree( message_buffer );
  352.       }
  353.    }
  354. }
  355.